package com.iot.ammeter.service.impl.android.user;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.iot.ammeter.constant.Constant;
import com.iot.ammeter.dto.app.register.AppUserRegisterDTO;
import com.iot.ammeter.dto.app.register.AppUserRegisterInfoDTO;
import com.iot.ammeter.dto.app.user.AppUserInfoDTO;
import com.iot.ammeter.dto.app.user.AppUserListDTO;
import com.iot.ammeter.dto.app.user.AppUserLoginDTO;
import com.iot.ammeter.dto.app.user.AppUserLoginInfoDTO;
import com.iot.ammeter.entity.android.bill.Bill;
import com.iot.ammeter.entity.android.user.AppUser;
import com.iot.ammeter.mapper.android.bill.BillMapper;
import com.iot.ammeter.mapper.android.user.AppUserMapper;
import com.iot.ammeter.query.android.AppUserQuery;
import com.iot.ammeter.responseResult.ResponseResult;
import com.iot.ammeter.service.android.user.AppUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iot.ammeter.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * app端用户表 服务实现类
 * </p>
 *
 * @author yjx
 * @since 2021-10-18
 */
@Service
@Transactional
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {

    private final AppUserMapper appUserMapper;
    private final BillMapper billMapper;
    private final RedisUtil redisUtil;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final SnowFlakeIdWorker snowFlakeIdWorker;

    public AppUserServiceImpl(AppUserMapper appUserMapper, RedisUtil redisUtil, BCryptPasswordEncoder bCryptPasswordEncoder,
                              SnowFlakeIdWorker snowFlakeIdWorker, BillMapper billMapper) {
        this.appUserMapper = appUserMapper;
        this.redisUtil = redisUtil;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.snowFlakeIdWorker = snowFlakeIdWorker;
        this.billMapper = billMapper;
    }

    /**
     * app用户登录
     *
     * @param appUserLoginDTO app端登录传输对象DTO
     * @return
     */
    @Override
    public Map<String, String> appUserLogin(AppUserLoginDTO appUserLoginDTO) {
        /**
         * 定义map处理请求数据成功与否
         */
        Map<String, String> message = new HashMap<>();
        /**
         * 校验邮箱密码
         */
        String emailTODO = appUserLoginDTO.getEmail().trim();
        String passwordTODO = appUserLoginDTO.getPassword().trim();
        if (StringUtils.isEmpty(passwordTODO.trim())) {
            message.put("fail", "密码不能为空");
            return message;
        }
        if (StringUtils.isEmpty(emailTODO.trim())) {
            message.put("fail", "邮箱不能为空");
            return message;
        }
        if (!CheckTool.isEmail(emailTODO.trim())) {
            message.put("fail", "邮箱格式有误");
            return message;
        }
        /**
         * 查询数据库，匹配邮箱密码
         */
        AppUser appUserFromDb = appUserMapper.selectAppUserByEmail(emailTODO);
        if (appUserFromDb == null) {
            message.put("fail", "账号密码错误");
            return message;
        }

        /**
         * 匹配密码
         */
        boolean matches = bCryptPasswordEncoder.matches(passwordTODO, appUserFromDb.getPassword());
        if (!matches) {
            message.put("fail", "账号密码错误");
            return message;
        }

        /**
         * 获取用户信息，菜单列表，角色，用户名
         */
        AppUserLoginInfoDTO appUserLoginInfoDTO = appUserMapper.selectAppUserInfoByEmail(emailTODO);

        /**
         * 生成token存入map中
         */
        Map<String, Object> claims = AppClaimsUtil.appUserToClaims(appUserLoginInfoDTO);
        String token = JwtUtil.createToken(claims, -1);
        if (token != null) {
            message.put("token", token);
        }
        return message;
    }

    /**
     * app端用户注册
     *
     * @param appUserRegisterDTO app端用户传输对象DTO
     * @return
     */
    @Override
    public Map<String, String> appUserRegister(AppUserRegisterDTO appUserRegisterDTO) {
        /**
         * 定义map处理请求数据成功与否
         */
        Map<String, String> message = new HashMap<>();
        /**
         * 实体,数据校验
         */
        String emailToDb = appUserRegisterDTO.getEmail().trim();
        String passwordToDb = appUserRegisterDTO.getPassword().trim();
        String captcha = appUserRegisterDTO.getCaptcha().trim();
        /**
         * 判断数据
         */
        if (StringUtils.isEmpty(captcha)) {
            message.put("fail", "验证码不能为空");
            return message;
        }
        if (StringUtils.isEmpty(emailToDb)) {
            message.put("fail", "邮箱不能为空");
            return message;
        }
        if (StringUtils.isEmpty(passwordToDb)) {
            message.put("fail", "密码不能为空");
            return message;
        }
        if (!CheckTool.isEmail(emailToDb)) {
            message.put("fail", "邮箱格式有误");
            return message;
        }
        /**
         * 检查是否存在该用户
         */
        if (appUserMapper.emailExists(emailToDb) != null) {
            message.put("fail", "邮箱已注册");
            return message;
        }
        /**
         * 验证码与redis中存放的验证码匹配，相等放行，不相等提示错误,匹配成功后，移除redis中的验证码
         */
        String redisCaptcha = (String) redisUtil.get(Constant.Redis.REGISTERED_APP_USER + emailToDb.trim());
        if (redisCaptcha == null) {
            message.put("fail", "验证码已过期");
            return message;
        }
        System.out.println(!redisCaptcha.equals(captcha));
        if (!redisCaptcha.equals(captcha)) {
            message.put("fail", "验证码有误");
            return message;
        }
        redisUtil.del(Constant.Redis.REGISTERED_APP_USER + emailToDb.trim());
        /**
         *  对密码进行加密
         */
        passwordToDb = bCryptPasswordEncoder.encode(passwordToDb);
        /**
         * 生成id信息
         */
        long appBalanceId = snowFlakeIdWorker.nextId();
        long appBillId = snowFlakeIdWorker.nextId();
        long appUserId = snowFlakeIdWorker.nextId();
        /**
         * 创建AppUser对象
         */
        AppUser appUser = new AppUser();
        /**
         * 补全app_user表数据并插入数据库
         */
        appUser.setAppUserId(String.valueOf(appUserId));
        appUser.setUserName("默认用户名");
        appUser.setPassword(passwordToDb);
        BigDecimal balance_init = new BigDecimal(Double.toString(0));
        appUser.setBalance(balance_init);
        appUser.setPhone(null);
        appUser.setEmail(emailToDb);
        appUser.setAvatar(null);
        appUser.setCreateTime(LocalDateTime.now());
        appUser.setUpdateTime(LocalDateTime.now());
        appUser.setUseBalanceDefault(true);
        appUser.setRoomId(null);
        /**
         * 创建app端费用账单表对象
         */
        Bill appBill = new Bill();
        /**
         * 补全app端费用账单表信息
         */
        appBill.setBillId(String.valueOf(appBillId));
        /**
         * 缴费情况：默认未缴费
         * 缴费时间：默认为空
         * 设备id默认为空
         * 手机号码默认为空
         */
        appBill.setPaid("0");
        appBill.setPaidDate(null);
        appBill.setBalanceId(String.valueOf(appBalanceId));
        appBill.setCreateTime(LocalDateTime.now());
        appBill.setUpdateTime(LocalDateTime.now());
        appBill.setEquipmentIdentifier(null);
        appBill.setAppUserPhone(null);
        appBill.setAppUserId(String.valueOf(appUserId));

        /**
         * 插入app_user表数据库并补全用户信息
         */
        int appUserResult = appUserMapper.insert(appUser);
        int appBillResult = billMapper.insert(appBill);
        /**
         *默认result为0
         * 当插入成功result为1
         */
        int result = 0;
        if (appUserResult > 0 && appBillResult > 0) {
            result = 1;
        }
        /**
         * 创建appUserRegisterInfoDTO
         * 并且返回响应数据对象
         */
        AppUserRegisterInfoDTO appUserRegisterInfoDTO = new AppUserRegisterInfoDTO();
        appUserRegisterInfoDTO.setAppUserId(String.valueOf(appUserId));
        appUserRegisterInfoDTO.setBalance(balance_init);
        appUserRegisterInfoDTO.setEquipmentIdentifier(null);
        appUserRegisterInfoDTO.setUseBalanceDefault(true);
        /**
         * 封装对象数据，用于生成token
         */
        Map<String, Object> clamis = new HashMap<>();
        clamis.put("appUserId", appUserRegisterInfoDTO.getAppUserId());
        clamis.put("balance", appUserRegisterInfoDTO.getBalance());
        clamis.put("equipmentIdentifier", appUserRegisterInfoDTO.getEquipmentIdentifier());
        clamis.put("usrBalanceDefault", appUserRegisterInfoDTO.getUseBalanceDefault());
        /**
         * 生成token
         */
        String token = JwtUtil.createToken(clamis, -1);
        /**
         * 封装数据
         */
        if (token != null) {
            message.put("token", token);
        }
        return message;
    }

    /**
     * 检验邮箱是否被注册
     *
     * @param email 邮箱号
     * @return
     */
    @Override
    public ResponseResult appEmailIsExists(String email) {
        /**
         * 校验数据
         */
        if (StringUtils.isEmpty(email.trim())) {
            return ResponseResult.FAILED("邮箱不能为空");
        }
        if (!CheckTool.isEmail(email.trim())) {
            return ResponseResult.FAILED("邮箱格式有误");
        }
        /**
         * 查询，存在返回一个不为空的对象。反之返回一个为空的对象
         */
        AppUser appUser = appUserMapper.emailExists(email.trim());
        System.out.println(appUser);
        return appUser != null ? ResponseResult.FAILED("邮箱已被注册") : ResponseResult.SUCCESS("邮箱可用");
    }

    /**
     * app用户查询信息
     *
     * @param email app用户邮箱
     * @return
     */
    @Override
    public AppUserInfoDTO selectAppUserByEmail(String email) {
        return appUserMapper.selectAppInfo(email);
    }

    /**
     * 获取android用户列表
     *
     * @param page         页码
     * @param pageSize     每页数量
     * @param appUserQuery 查询条件
     * @return android用户列表
     */
    @Override
    public IPage<AppUserListDTO> listAppUser(int page, int pageSize, AppUserQuery appUserQuery) {
        /**
         * 封装翻页对象
         */
        Page<AppUserListDTO> pages = new Page<>(page, pageSize);
        /**
         * 查询
         */
        IPage<AppUserListDTO> iPage = appUserMapper.selectAppUserPage(pages, appUserQuery);
        return iPage;
    }
}
